Backlogで「リンク付きの課題キーと件名」を取得するボタンを追加するChrome拡張機能を作ってみた
データアナリティクス事業本部のueharaです。
今回はBacklogで「リンク付きの課題キーと件名」を取得するボタンを追加するChrome拡張機能を作ってみたいと思います。
2024/10/30 追記
はじめに
本記事で紹介しているコードは以下リポジトリにアップロードしています。
何がしたいのか?
Backlogには標準機能として課題キーと件名をコピーするボタンがあります。
しかし、少なくともMac Bookではこのボタンでコピーを行ったあと、Google Docsに貼り付けると次のようになります。
うーむ、、、
私としては、以下のようなプレーンなリンク付きテキストで貼り付けられるのが希望です。
今までは 「①一旦書式無しテキストで貼り付け ⇒ ②課題チケットに戻りURLをコピー ⇒ ③テキストにリンクを紐付け」 という手順を踏んでこの形にしていたのですが、流石に面倒になってきたので、今回Chromeの拡張機能を作ってみました。
どう対応したのか?
標準ボタンの隣に1つボタンを追加し、1クリックで上記の「プレーンなリンク付きテキスト」を取得することができるChromeの拡張機能を作成しました。
これにより今までのストレスが無くなり、快適にGoogle Docsに課題チケットを転記することができるようになりました。
実装
ファイル構成
今回作成した拡張機能のファイル構成は次の通りです。
my_extension
├ css
| └ style.css
├ icons
| ├ icon16.png
| ├ icon48.png
| └ icon128.png
├ js
| └ content.js
└ manifest.json
manifest.json
詳しい説明は省略しますが、Chromeの拡張機能を作る際にはまず manifest.json
が必要になります。
現状使われているものとしてはmanifest V2とmanifest V3がありますが、V2の方は2023年6月に例外なく動作しなくなります。
今から作成する場合はV3にしておく方が無難です。
ということで、以下のように書いてみました。
{
"name": "BacklogLinkCopy",
"version": "0.1.0",
"manifest_version": 3,
"description": "For Backlog Link Copy",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},
"host_permissions": [
"https://<クラメソのサブドメイン>.backlog.jp/*"
],
"permissions": [
"clipboardWrite",
"activeTab"
],
"content_scripts": [{
"matches": [
"https://<クラメソのサブドメイン>.backlog.jp/*"
],
"css": [
"css/style.css"
],
"js": [
"js/content.js"
],
"run_at": "document_end",
"all_frames": true
}]
}
今回、ターゲットのURLとして特定ドメインのBacklogに限定していますが、他のBacklogでも使いたい場合はURLを追加するであったり、*
を使うなどで対応することができます。
※冒頭に記載したGitHubのリポジトリでは *
で記載をしています
それぞれの記載についてはなんとなく文字からイメージがつくかと思いますが、より詳しく知りたい方は公式のドキュメントをご確認ください。
style.css
追加するボタンのスタイルを決めます。
今回はできるだけ標準のボタンと近い形となるよう、以下のように設定しました。
.new-button {
position: absolute;
margin-left: 7px;
background-color: #3ea8ff;
color: white;
line-height: 1;
height: 32px;
width: 32px;
text-align: center;
border: none;
border-radius: 50%;
font-size: 18px;
cursor: pointer;
}
.new-button:active{
background-color: #0f83fd;
color: white;
}
content.js
こちらが今回のメインとなる部分です。
console.log("[DEBUG] load extension");
window.addEventListener('load', main, false);
window.addEventListener('popstate', main);
window.addEventListener('pushstate', main);
window.addEventListener('replacestate', main);
const loadFontAwesome = () => {
let link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://use.fontawesome.com/releases/v5.13.1/css/all.css';
document.head.insertAdjacentElement('beforeEnd', link);
};
function main(event) {
const jsInitCheckTimer = setInterval(jsLoaded, 100);
// fontawesomeのロード
loadFontAwesome();
function jsLoaded() {
if (document.querySelector('#copyKey-help') != null) {
clearInterval(jsInitCheckTimer);
// ボタンを追加する場所を選択
let existingButton = document.querySelector('#copyKey-help');
// ボタン要素を作成
let newButton = document.createElement('button');
// ボタンのテキストを設定
newButton.innerHTML = '<i class="far fa-copy"></i>';
newButton.classList.add('new-button');
// ボタンを追加
existingButton.appendChild(newButton);
// ボタンが押された時の処理
newButton.addEventListener('click', function() {
let currentUrl = window.location.href;
let ticket_key = document.querySelector(".ticket__key-number").innerText;
let subject = document.querySelector(".markdown-body").innerText;
let title = ticket_key + " " + subject;
let htmlLink = '<a href="' + currentUrl + '">' + title + '</a>';
const blob = new Blob([htmlLink], { type: 'text/html' });
const blobPlain = new Blob([title], { type: 'text/plain' });
const data = [new window.ClipboardItem({ 'text/html': blob, 'text/plain': blobPlain })];
navigator.clipboard.write(data)
.then(function() {
console.log('Title copied to clipboard');
})
.catch(function(error) {
console.error('Failed to copy title: ', error);
});
});
}
}
}
そこまで難しい処理は無いですが、1点だけ注意したい部分があります。
今回標準機能のボタン #copyKey-help
の隣に新しいボタンを追加したいのですが、標準ボタンは動的に生成される要素のため、単純に.appendChild(newButton)
をしようとすると高確率でエラーとなります(標準ボタンの生成前にappend処理が動いてしまう)。
したがって、動的なページの読み込みが完了してからChrome拡張機能を実行するようにしています。
また、今回ボタンのアイコンにFontAwesomeを利用したかったので、ヘッダにスタイルシートを追加する処理も記載しています。
冒頭で示した「プレーンなリンク付きテキスト」は以下のような形で作成することができます。
let htmlLink = '<a href="' + currentUrl + '">' + title + '</a>';
const blob = new Blob([htmlLink], { type: 'text/html' });
const blobPlain = new Blob([title], { type: 'text/plain' });
const data = [new window.ClipboardItem({ 'text/html': blob, 'text/plain': blobPlain })];
作成した拡張機能の読み込み
作成したオレオレ拡張機能の読み込みは、Chromeの拡張機能のページにあるデベロッパーモードをONにし、「パッケージ化されていない拡張機能を読み込む」ボタンから実施することができます。
その後、my_extension
フォルダを選択すれば拡張機能の読み込みは完了です。
※私はアイコンをBacklogのロゴに設定したので、上記のような表示となっています。(my_extensionフォルダ配下のiconsに配置している.png
ファイルが表示されるアイコンになります)
最後に
今回は、Backlogで「リンク付きの課題キーと件名」を取得するボタンを追加するChrome拡張機能を作ってみました。
本記事がどなたかの参考になりましたら幸いです。
参考文献
- Welcome to Manifest V3
- google chrome extension - How to get a content script to load AFTER a page's Javascript has executed? - Stack Overflow
- Chrome 拡張機能で FontAwesome を使う
- javascript - TypeError: Failed to construct 'ClipboardItem': Failed to convert value to 'Blob' - Stack Overflow
- JavaScriptのClipboard APIでリッチテキスト(書式付きテキスト)をコピーする